package net.anzhuo.controller.es;


import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;

import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.extern.slf4j.Slf4j;
import net.anzhuo.common.base.BaseController;
import net.anzhuo.common.utils.CompanyNameUtils;
import net.anzhuo.common.utils.DateUtil;
import net.anzhuo.common.utils.RandomGUID;
import net.anzhuo.entity.GsBase;
import net.anzhuo.entity.GsPriority;
import net.anzhuo.entity.GsQuery;
import net.anzhuo.entity.es.Paging;
import net.anzhuo.entity.es.Result;
import net.anzhuo.entity.es.SearchResult;
import net.anzhuo.service.GsBaseService;
import net.anzhuo.service.GsPriorityService;
import net.anzhuo.service.GsQueryService;

@RestController
@Slf4j
public class EsController extends BaseController {

	@Autowired
	private TransportClient client;
	
	
	@Autowired
	private GsBaseService gsBaseService;
	
	
	@Autowired
	private GsQueryService gsQueryService;
	
	

	@RequestMapping("/search")
	public SearchResult list(String keyword, String pageIndex, Integer pageSize) {
		
		log.info("===>search_keyword="+keyword+", pageIndex="+pageIndex+", pageSize="+pageSize);
		long startTime=System.currentTimeMillis();
		if (StringUtils.isBlank(pageIndex) || "0".equals(pageIndex)) {
			pageIndex = "1";
		}
		if (pageSize==null || pageSize<1 || pageSize>30) {
			pageSize = 10;
		}
		
		keyword = keyword.trim();
		boolean firstMatch=false;
		QueryStringQueryBuilder  queryPre = null;
		if(keyword!=null &&!keyword.equals("")&&!keyword.equals("未公开")&&!keyword.equals("-"))
		{
			String q="\""+keyword+"\"";
			queryPre = new QueryStringQueryBuilder(q).field("credit_code").defaultOperator(Operator.AND);
		}else
		{

			String q="\""+keyword+"\"";
			queryPre = new QueryStringQueryBuilder(q).field("name").defaultOperator(Operator.AND);
		}
		if(queryPre!=null)
		{				
		SearchResponse response = client.prepareSearch("gs").setTypes("gs_base").setQuery(queryPre).addSort("weight", SortOrder.DESC).addSort("_score", SortOrder.DESC).setFrom(0).setSize(1000).execute().actionGet();
		log.info("first QueryName size="+response.getHits().getTotalHits());
		if (response.getHits().getTotalHits()>0) {
			{
				firstMatch=true;
				
			}
			}
		}
	log.info("firstMatch="+firstMatch);

	if(!firstMatch)	
	{
		GsBase gsBase=new GsBase();
		gsBase=gsBaseService.getByName(CompanyNameUtils.getChineseBraces(keyword));
		if(gsBase==null)
		{
			gsBase=gsBaseService.getByName(CompanyNameUtils.getEnglishBraces(keyword));
		}
		//log.info("database Name="+gsBase.getName()+",database md5="+gsBase.getMd5());
		String docId="";
		boolean isExists=false;
		boolean isExistsEs=false;
		if(gsBase!=null)
		{
			isExists=true;
			if(gsBase.getCreditCode()!=null)
			{
				QueryStringQueryBuilder  query = null;
			if(gsBase.getCreditCode()!=null &&!gsBase.getCreditCode().equals("")&&!gsBase.getCreditCode().equals("未公开")&&!gsBase.getCreditCode().equals("-"))
			{
				String q="\""+gsBase.getCreditCode()+"\"";
				query = new QueryStringQueryBuilder(q);
				query.field("credit_code");
			}else
			{

				String q="\""+gsBase.getName()+"\"";
				query = new QueryStringQueryBuilder(q);
				query.field("name");
			}
			if(query!=null)
			{				
				Hashtable<String,String> ht=new Hashtable<String,String>();
				Hashtable<String,Integer> ht2=new Hashtable<String,Integer>();
			SearchResponse response = client.prepareSearch("gs").setTypes("gs_base").setQuery(query).addSort("weight", SortOrder.DESC).addSort("_score", SortOrder.DESC).setFrom(0).setSize(1000).execute().actionGet();
			log.info("first QueryName size="+response.getHits().getTotalHits());
			if (response.getHits().getTotalHits()>0) {
				{
					
					for (SearchHit searchHit : response.getHits()) {
						docId=searchHit.getId();
						String md5=(String)searchHit.getSource().get("md5");
						String Name=(String)searchHit.getSource().get("name");
						String CreditCode=(String)searchHit.getSource().get("credit_code");
						if(gsBase.getMd5().equals(md5)&&gsBase.getName().equals(Name))
						{
							if(!ht.containsKey(gsBase.getMd5()+gsBase.getName()))
							{
							ht.put(gsBase.getMd5()+gsBase.getName(), docId);
							int x=1;
							ht2.put(gsBase.getMd5()+gsBase.getName(), x);
							}else
							{
								int count=ht2.get(gsBase.getMd5()+gsBase.getName());
								count++;
								ht2.put(gsBase.getMd5()+gsBase.getName(), count);
								ht.put(gsBase.getMd5()+gsBase.getName(), docId);
							}
							isExistsEs=true;							
							log.info("isExistsEs="+isExistsEs+",database md5="+gsBase.getMd5());
						}
						if(ht2.get(gsBase.getMd5()+gsBase.getName())!=null)
						{
						if (ht2.get(gsBase.getMd5()+gsBase.getName())>1){
					
							DeleteResponse responseDelete = client.prepareDelete("gs", "gs_base", ht.get(gsBase.getMd5()+gsBase.getName()))  
					                .execute().actionGet();  
					
					        log.info("delete docId="+responseDelete.getId()+",name="+Name+",md5="+md5+",creditCode="+CreditCode);
						}
						}
						log.info("a docId="+docId+",name="+Name+",md5="+md5+",creditCode="+CreditCode);
					}
					}
				}
			}
			}
		}
		
		if(gsBase==null)
		{
		gsBase=gsBaseService.getByCreditCode(keyword);
		}
		
		//not exists
		if(gsBase!=null)
		{
			isExists=true;
		}else
		{
			
			
		}
		
		if(!isExists)
		{
			GsQuery gsQuery=new GsQuery();
			boolean isCredit=false;
			if(keyword.length()==18)
			{
				int credit=0;
				try {
				credit=Integer.parseInt(keyword.substring(0, 4));
				isCredit=true;
				}catch(Exception e)
				{
					isCredit=false;
				}
			    if(isCredit)
			    {
				gsQuery.setCreditCode(keyword);
			    }else
			    {
			    	gsQuery.setName(keyword);
			    }
			}else
			{
				gsQuery.setName(keyword);
			}
			
			if(gsQuery.getName()!=null&&!gsQuery.getName().equals(""))
			{
			gsQuery.setStatus("0");
			gsQuery.setKeyNo(RandomGUID.generatorGUID());
			List<GsQuery> list=gsQueryService.getBycoMd5(gsQuery);
			gsQuery.setUpdateTime(DateUtil.getDate("yyyy-MM-dd"));
			if(list.size()==0)
			{
			 gsQueryService.save(gsQuery);
			}
			}
			
		}
		log.info("es exists="+isExistsEs);
		String weight=null;
		if(isExists&&!isExistsEs&&gsBase!=null)
		{
			log.info("database exists="+isExists+",es exists="+isExistsEs+"gsBase's name="+gsBase.getName()+",md5="+gsBase.getMd5());
			docId="";
			String updateDocId="";

			QueryStringQueryBuilder query=null;
			String q="\""+gsBase.getName()+"\"";
			query = new QueryStringQueryBuilder(q);
			query.field("name");
			int i=0;
			SearchResponse response = client.prepareSearch("gs").setTypes("gs_base").setQuery(query).addSort("weight", SortOrder.DESC).addSort("_score", SortOrder.DESC).setFrom(0).setSize(1000).execute().actionGet();
			
			
			if (response.getHits().getTotalHits()>0) {
				{
					for (SearchHit searchHit : response.getHits()) {
						
						String md5=(String)searchHit.getSource().get("md5");
						 weight=searchHit.getSource().get("weight").toString();
						isExistsEs=true;
						if(!gsBase.getMd5().equals(md5)||(gsBase.getMd5().equals(md5)&&i>=1))
						{
							docId=searchHit.getId();
							DeleteResponse responseDelete = client.prepareDelete("gs", "gs_base", docId)  
					                .execute().actionGet();  
					        docId="";
					        log.info(" delete docId="+responseDelete.getId()+",name="+(String)searchHit.getSource().get("name")+",md5="+(String)searchHit.getSource().get("md5"));
						}else
						{
							updateDocId=searchHit.getId();
						}
						i++;
						log.info("b docId="+docId+",name="+(String)searchHit.getSource().get("name")+",md5="+(String)searchHit.getSource().get("md5"));
					}
			   }
			}else
				{
					if(!StringUtils.isEmpty(gsBase.getCreditCode()))
					{
						if(!gsBase.getCreditCode().equals("未公开")&&!gsBase.getCreditCode().equals("-"))
						{
							 q="\""+gsBase.getCreditCode()+"\"";
							query = new QueryStringQueryBuilder(q);
							query.field("credit_code");
					    i=0;
					    response = client.prepareSearch("gs").setTypes("gs_base").setQuery(query).addSort("weight", SortOrder.DESC).addSort("_score", SortOrder.DESC).setFrom(0).setSize(1000).execute().actionGet();
					    for (SearchHit searchHit : response.getHits()) {
							
							String md5=(String)searchHit.getSource().get("md5");
							 weight=(String)searchHit.getSource().get("weight");
							isExistsEs=true;
							if(!gsBase.getMd5().equals(md5)||(gsBase.getMd5().equals(md5)&&i>=1))
							{
								docId=searchHit.getId();
								DeleteResponse responseDelete = client.prepareDelete("gs", "gs_base", docId)  
						                .execute().actionGet();  
						        docId="";
						        log.info(" delete docId="+responseDelete.getId()+",name="+(String)searchHit.getSource().get("name")+",md5="+(String)searchHit.getSource().get("md5"));
							}else
							{
								updateDocId=searchHit.getId();
							}
							i++;
							log.info("b docId="+docId+",name="+(String)searchHit.getSource().get("name")+",md5="+(String)searchHit.getSource().get("md5"));
						}
						}
					}else
					{
						 q="\""+gsBase.getName()+"\"";
							query = new QueryStringQueryBuilder(q);
							query.field("name");
						    i=0;
						    response = client.prepareSearch("gs").setTypes("gs_base").setQuery(query).addSort("weight", SortOrder.DESC).addSort("_score", SortOrder.DESC).setFrom(0).setSize(1000).execute().actionGet();
						    for (SearchHit searchHit : response.getHits()) {
								
								String md5=(String)searchHit.getSource().get("md5");
								 weight=(String)searchHit.getSource().get("weight");
								isExistsEs=true;
								if(!gsBase.getMd5().equals(md5)||(gsBase.getMd5().equals(md5)&&i>=1))
								{
									docId=searchHit.getId();
									DeleteResponse responseDelete = client.prepareDelete("gs", "gs_base", docId)  
							                .execute().actionGet();  
							        docId="";
							        log.info(" delete docId="+responseDelete.getId()+",name="+(String)searchHit.getSource().get("name")+",md5="+(String)searchHit.getSource().get("md5"));
								}else
								{
									updateDocId=searchHit.getId();
								}
								i++;
								log.info("b docId="+docId+",name="+(String)searchHit.getSource().get("name")+",md5="+(String)searchHit.getSource().get("md5"));
							}
					}
				}
						
				
			
			int iweight=0;
			if(updateDocId!=null&&!updateDocId.equals(""))
			{
			log.info("updateDocId="+updateDocId);
			UpdateRequest updateRequest = new UpdateRequest();
	        updateRequest.index("gs");
	        updateRequest.type("gs_base");
	        updateRequest.id(""+updateDocId);
	        
	        if(StringUtils.isEmpty(gsBase.getWeight())&&StringUtils.isEmpty(weight))
	        {
	        	iweight=1;
	        }else if(StringUtils.isNotEmpty(gsBase.getWeight())&&StringUtils.isEmpty(weight))
	        {
	        	iweight=Integer.parseInt(gsBase.getWeight());
	        }else if(StringUtils.isEmpty(gsBase.getWeight())&&StringUtils.isNotEmpty(weight))
	        {
	        	iweight=Integer.parseInt(weight);
	        	iweight++;
	        }
	        try {
				updateRequest.doc(XContentFactory.jsonBuilder()
				        .startObject()
				        // 对没有的字段添加, 对已有的字段替换
				            .field("name", gsBase.getName())
				            .field("legal",gsBase.getLegal())
				            .field("name2",gsBase.getName2())
				            .field("tel",gsBase.getTel())
				            .field("email",gsBase.getEmail())
				            .field("web_site",gsBase.getWebSite())
				            .field("reg_zb",gsBase.getRegZb())
				            .field("reg_time",gsBase.getRegTime())
				            .field("enterprise_status",gsBase.getEnterpriseStatus())
				            .field("credit_code",gsBase.getCreditCode())
				            .field("enterprise_type",gsBase.getEnterpriseType())
				            .field("reg_address",gsBase.getRegAddress())
				            .field("province",gsBase.getProvince())
				            .field("city",gsBase.getCity())
				            .field("area",gsBase.getArea())
				            .field("md5",gsBase.getMd5())
				            .field("industry",gsBase.getIndustry())
				            .field("oper_scope",gsBase.getOperScope())
				            .field("year",gsBase.getYear())
				            .field("weight",iweight+"")
				        .endObject()).setRefreshPolicy(RefreshPolicy.IMMEDIATE);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        UpdateResponse responseD=null;
			try {
				responseD = client.update(updateRequest).get();
				// 打印
			
				log.info("Update es doc success!");
		        String index = responseD.getIndex();
		        String type = responseD.getType();
		        String id = responseD.getId();
		        long version = responseD.getVersion();
		        System.out.println(index + " : " + type + ": " + id + ": " + version);
			} catch (InterruptedException | ExecutionException e) {
				// TODO Auto-generated catch block
				log.info("201");
				log.info("Update es doc fail!");
				e.printStackTrace();
			}
	        
	        
		}else
		{
			
			try {
			 BulkRequestBuilder bulkRequest = client.prepareBulk();
			 bulkRequest.setRefreshPolicy(RefreshPolicy.IMMEDIATE);
				bulkRequest.add(client.prepareIndex("gs", "gs_base").setSource(XContentFactory.jsonBuilder()
			                .startObject()
			                .field("name", gsBase.getName())
				            .field("legal",gsBase.getLegal())
				            .field("name2",gsBase.getName2())
				            .field("tel",gsBase.getTel())
				            .field("email",gsBase.getEmail())
				            .field("web_site",gsBase.getWebSite())
				            .field("reg_zb",gsBase.getRegZb())
				            .field("reg_time",gsBase.getRegTime())
				            .field("enterprise_status",gsBase.getEnterpriseStatus())
				            .field("credit_code",gsBase.getCreditCode())
				            .field("enterprise_type",gsBase.getEnterpriseType())
				            .field("reg_address",gsBase.getRegAddress())
				            .field("province",gsBase.getProvince())
				            .field("city",gsBase.getCity())
				            .field("area",gsBase.getArea())
				            .field("md5",gsBase.getMd5())
				            .field("industry",gsBase.getIndustry())
				            .field("oper_scope",gsBase.getOperScope())
				            .field("year",gsBase.getYear())
				            .field("weight",gsBase.getWeight())
			                .endObject()
			              )
		          );
				
				
			//	BulkResponse bulkResponse = bulkRequest.get();

		        
		      
		        

		        BulkResponse bulkResponse = bulkRequest.execute().actionGet();
		        if (bulkResponse.hasFailures()) {
		            // process failures by iterating through each bulk response item
		            System.out.println(bulkResponse.getItems().toString());
		            log.info("201");
		            log.info("Update es doc fail!");
		        }
		        bulkRequest = client.prepareBulk();
		        log.info("200");
		        log.info("Add es doc success!");
			}catch(Exception e)
			{
				log.error(" add es error.");
			}
			
		}
		
		}
	}
			
	
		QueryBuilder query = QueryBuilders.boolQuery()
				.must(QueryBuilders.boolQuery()
					.should(QueryBuilders.termQuery("name2", keyword))
					.should(QueryBuilders.matchQuery("credit_code", keyword))
					.should(QueryBuilders.matchQuery("name", keyword).operator(Operator.AND))
					.should(QueryBuilders.termQuery("legal", keyword)))
				.must(QueryBuilders.boolQuery()
					.should(QueryBuilders.matchPhraseQuery("enterprise_type", "有限责任公司"))
					.should(QueryBuilders.matchPhraseQuery("enterprise_type", "股份有限公司")));
		
		SearchResponse response =  client.prepareSearch("gs").setTypes("gs_base").setQuery(query).
				addSort("weight", SortOrder.DESC).
				addSort("_score", SortOrder.DESC).setFrom((Integer.parseInt(pageIndex)-1)*pageSize).setSize(pageSize).execute().actionGet();
		SearchResponse response2 = null;
		if (response.getHits().getTotalHits() == 0) {
			log.info("====>search_no_result_keyword="+keyword);
			query = QueryBuilders.boolQuery()
					.must(QueryBuilders.boolQuery()
						.should(QueryBuilders.matchQuery("name", keyword).operator(Operator.AND)))
					.mustNot(QueryBuilders.matchPhraseQuery("enterprise_type", "有限责任公司"))
					.mustNot(QueryBuilders.matchPhraseQuery("enterprise_type", "股份有限公司"));
			response2 = client.prepareSearch("gs").setTypes("gs_base").setQuery(query).
					addSort("weight", SortOrder.DESC).
					addSort("_score", SortOrder.DESC).setFrom((Integer.parseInt(pageIndex)-1)*pageSize).setSize(pageSize).execute().actionGet();
		}
		
		SearchResult searchResult = new SearchResult();
		searchResult.setStatus("200");
		searchResult.setMessage("查询成功");
		
		Paging paging = new Paging();
		paging.setPageIndex(Integer.parseInt(pageIndex));
		paging.setPageSize(pageSize);
		paging.setTotalRecords((int)response.getHits().getTotalHits());
		searchResult.setPaging(paging);
		
		Result result = null;
		List<Result> resultList = new ArrayList<>();
		if (response2 == null) {
			for (SearchHit searchHit : response.getHits()) {
				result = new Result();
				result.setKeyNo((String)searchHit.getSource().get("md5"));
				result.setName((String)searchHit.getSource().get("name"));
				result.setOperName((String)searchHit.getSource().get("legal"));
				result.setStartDate((String)searchHit.getSource().get("reg_time"));
				result.setStatus((String)searchHit.getSource().get("enterprise_status"));
				result.setCreditCode((String)searchHit.getSource().get("credit_code"));
				resultList.add(result);
			}
		} else {
			for (SearchHit searchHit : response2.getHits()) {
				result = new Result();
				result.setKeyNo((String)searchHit.getSource().get("md5"));
				result.setName((String)searchHit.getSource().get("name"));
				result.setOperName((String)searchHit.getSource().get("legal"));
				result.setStartDate((String)searchHit.getSource().get("reg_time"));
				result.setStatus((String)searchHit.getSource().get("enterprise_status"));
				result.setCreditCode((String)searchHit.getSource().get("credit_code"));
				resultList.add(result);
			}
		}
		searchResult.setResult(resultList);
		 long endTime=System.currentTimeMillis();
		 float excTime=(float)(endTime-startTime)/1000;
		 log.info(" search 执行时间："+excTime+"s");
		return searchResult;
	}
}
